import 'package:app/core/utils/helpers/sp.dart';
import 'package:dio/dio.dart';

import 'global.dart';

class CacheObject {
  CacheObject(this.response)
      : timeStamp = DateTime.now().millisecondsSinceEpoch;
  Response response;
  int timeStamp;

  @override
  bool operator ==(other) {
    return response.hashCode == other.hashCode;
  }

  @override
  int get hashCode => response.realUri.hashCode;
}

class CacheInterceptor extends Interceptor {
  CacheInterceptor();

  final _cache = <String, CacheObject>{};

  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    var cacheObject = _cache[options.uri];

    bool refresh = options.extra['refresh'] == true;
    // 是否磁盘缓存
    bool cacheDisk = options.extra["cacheDisk"] == true;

    if (refresh) {
      // 内存缓存
      delete(options.uri.toString());
      // 删除磁盘缓存
      if (cacheDisk) {
        await SpUtil.instance.controller.box.remove(options.uri.toString());
      }
      print('${options.uri}: force refresh, ignore cache! \n');
      return handler.next(options);
    } else if (cacheObject != null) {
      print('cache hit: ${options.uri} \n');
      return handler.resolve(cacheObject.response);
    }
    // get强开缓存
    // get 请求，开启缓存
    if (options.extra["noCache"] != true &&
        options.method.toLowerCase() == 'get') {
      String key = options.extra["cacheKey"] ?? options.uri.toString();

      // 策略 1 内存缓存优先，2 然后才是磁盘缓存

      // 1 内存缓存
      var ob = _cache[key];
      if (ob != null) {
        //若缓存未过期，则返回缓存内容
        if ((DateTime.now().millisecondsSinceEpoch - ob.timeStamp) / 1000 <
            Global.CACHE_MAX_AGE) {
          handler.resolve(_cache[key].response);
        } else {
          //若已过期则删除缓存，继续向服务器请求
          _cache.remove(key);
        }
      }

      // 2 磁盘缓存
      if (cacheDisk) {
        var cacheData = SpUtil.instance.controller.box.read(key);
        if (cacheData != null) {
          handler.resolve(
            Response(
              statusCode: 200,
              data: cacheData,
              requestOptions: options,
            ),
          );
        }
      }
    }

    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) async {
    // _cache[response.requestOptions.uri] = response;
    await _saveCache(response);
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    print('onError: $err');
    super.onError(err, handler);
  }

  Future<void> _saveCache(Response object) async {
    RequestOptions options = object.requestOptions;

    // 只缓存 get 的请求
    if (options.extra["noCache"] != true &&
        options.method.toLowerCase() == "get") {
      // 策略：内存、磁盘都写缓存

      // 缓存key
      String key = options.extra["cacheKey"] ?? options.uri.toString();

      // 磁盘缓存
      if (options.extra["cacheDisk"] == true) {
        await SpUtil.instance.controller.box.write(key, object.data);
      }

      // 内存缓存
      // 如果缓存数量超过最大数量限制，则先移除最早的一条记录
      if (_cache.length == Global.CACHE_MAX_COUNT) {
        _cache.remove(_cache[_cache.keys.first]);
      }

      _cache[key] = CacheObject(object);
    }
  }

  void delete(String key) {
    _cache.remove(key);
  }
}
